/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import path from 'path';

import { CommonConst } from '../const/common-const.js';
import { DistroFilterDimensionEnum } from '../enum/distro-filter-dimension-enum.js';
import { ProjectModel } from '../model/project/project-model.js';
import { ModuleBuildProfile } from '../options/build/module-build-profile.js';
import { ConfigJson } from '../options/configure/config-json-options.js';
import { checkIntersection, complementarySet, isSubset } from '../utils/array-util.js';
import { OhosLogger } from '../utils/log/ohos-logger.js';
import DistroFilterBuildOpt = ModuleBuildProfile.DistroFilterBuildOpt;
import ApiVersionOpt = ModuleBuildProfile.ApiVersionOpt;
import ScreenShapeOpt = ModuleBuildProfile.ScreenShapeOpt;
import ScreenWindowOpt = ModuleBuildProfile.ScreenWindowOpt;
import ConfigOptObj = ConfigJson.ConfigOptObj;
import ModuleTargetBuildOpt = ModuleBuildProfile.ModuleTargetBuildOpt;
import { parsingProfileName } from '../common/common-util.js';
import { findTargetProduct } from '../common/find-target-product.js';
import { ModuleJson } from '../options/configure/module-json-options.js';
import MetadataObj = ModuleJson.MetadataObj;
import { BuildDirConst } from '../const/build-directory-const.js';
import { CoreModuleModelImpl } from '../model/module/core-module-model-impl.js';
import { getJson5Obj } from '../utils/json-util.js';
import { resModelLoader } from '../utils/loader/file/res-model-loader.js';

/**
 * distroFilter相关配置及处理操作抽象类
 */
export abstract class DistroFilterHandler {
  protected logger: OhosLogger = OhosLogger.getLogger(DistroFilterHandler.name);
  protected nextDimensionHandler?: DistroFilterHandler;
  protected projectModel: ProjectModel;

  public constructor(projectModel: ProjectModel, distroFilterHandler?: DistroFilterHandler) {
    this.nextDimensionHandler = distroFilterHandler;
    this.projectModel = projectModel;
  }

  /**
   * 处理当前校验请求
   * @param sourceDistroFilterConfig
   * @param targetDistroFilterConfig
   */
  public abstract validateDistroFilterRequest(sourceDistroFilterConfig: DistroFilterConfig, targetDistroFilterConfig: DistroFilterConfig): void;

  /**
   * 获取当前维度distribution配置对象value
   * @param distroFilterConfig
   */
  public abstract getDimensionValue(distroFilterConfig: DistroFilterConfig): number[] | string[] | undefined;

  /**
   * 设置下一个校验维度
   * @param nextDimensionHandler
   */
  public setNextDimensionHandler(nextDimensionHandler: DistroFilterHandler): void {
    this.nextDimensionHandler = nextDimensionHandler;
  }

  /**
   * 执行校验
   * @param distroFilterConfigList distroFilter配置对象集合
   */
  public executeValidate(distroFilterConfigList: DistroFilterConfig[]): void {
    // 先检查distroFilter标签配置是否正确
    this.checkDistroFilterLabel();

    // 处理distroFilter配置对象集合 逐个互相校验
    for (let sourceIndex = 0; sourceIndex < distroFilterConfigList.length; sourceIndex++) {
      for (let targetIndex = distroFilterConfigList.length - 1; targetIndex > sourceIndex; targetIndex--) {
        this.validateDistroFilterRequest(distroFilterConfigList[sourceIndex], distroFilterConfigList[targetIndex]);
      }
    }
  }

  /**
   * 处理指定维度校验请求
   * @param sourceDistroFilterConfig
   * @param targetDistroFilterConfig
   * @param dimensionName ['apiVersion','screenShape','screenWindow'...]
   * @protected
   */
  protected doRequest(sourceDistroFilterConfig: DistroFilterConfig, targetDistroFilterConfig: DistroFilterConfig, dimensionName: string): void {
    const sourceEntryModule = sourceDistroFilterConfig.moduleName;
    const targetEntryModule = targetDistroFilterConfig.moduleName;
    const sourceValue = this.getDimensionValue(sourceDistroFilterConfig);
    const targetValue = this.getDimensionValue(targetDistroFilterConfig);
    const withoutSourceValue = sourceValue === undefined;
    const withoutTargetValue = targetValue === undefined;
    const curModuleName = withoutSourceValue ? sourceEntryModule : targetEntryModule;
    const curModuleExecutableTargetNameList = DistroFilterHandler.getCurModuleExecutableTargetNameList(this.projectModel, curModuleName);

    const isMultiTargets = DistroFilterHandler.validateMultiTarget(this.projectModel);
    if (withoutSourceValue !== withoutTargetValue) {
      // 相同判定维度必须在所有模块中同时配置
      const errorInfo = isMultiTargets ? 'executable targets' : 'modules';
      const errorDetail = isMultiTargets ? curModuleExecutableTargetNameList : curModuleName;
      const moduleModel = this.projectModel.getModuleModelByName(curModuleName) as CoreModuleModelImpl;
      const configFilePath = DistroFilterHandler.getDetailFilePath(this.projectModel, moduleModel);

      // 日志信息具体分类
      this.logger
        ._buildError(`${dimensionName} is not configured for all ${errorInfo}.`)
        ._detail(`Ensure that ${dimensionName} is configured for all ${errorInfo} [${errorDetail}].`)
        ._file(configFilePath)
        ._printErrorAndExit();
    }

    // 若当前指定判定维度配置为空 或 各模块间配置存在交集导致校验失败, 则进行下一维度判断
    if (
      (this.checkDimensionConfigEmpty(sourceDistroFilterConfig, dimensionName) && this.checkDimensionConfigEmpty(targetDistroFilterConfig, dimensionName)) ||
      checkIntersection(sourceValue!, targetValue!)
    ) {
      const sourceModuleExecutableTargetNameList = DistroFilterHandler.getCurModuleExecutableTargetNameList(this.projectModel, sourceEntryModule);
      const targetModuleExecutableTargetNameList = DistroFilterHandler.getCurModuleExecutableTargetNameList(this.projectModel, targetEntryModule);
      const cause = isMultiTargets
        ? 'The configured distroFilter in all executable targets ' +
          `[${sourceModuleExecutableTargetNameList}] in '${sourceEntryModule}',` +
          ` [${targetModuleExecutableTargetNameList}] in '${targetEntryModule}' settings overlap.`
        : `The configured distroFilter in '${sourceEntryModule}' and '${targetEntryModule}' settings overlap.`;
      if (!this.nextDimensionHandler) {
        this.logger
          ._buildError(cause)
          ._detail('Ensure that the distroFilter settings do not overlap or add new dimensions for distroFilter.')
          ._printErrorAndExit();
        return;
      }
      this.nextDimensionHandler.validateDistroFilterRequest(sourceDistroFilterConfig, targetDistroFilterConfig);
    }
  }

  /**
   * 获取指定校验维度distroFilter对象
   * @param distroFilterObj distroFilter对象
   * @param dimensionName 指定校验维度
   */
  public getDistroFilterObjByDimension(
    distroFilterObj: DistroFilterBuildOpt | undefined,
    dimensionName: string,
  ): ApiVersionOpt | ScreenShapeOpt | ScreenWindowOpt | undefined {
    if (!distroFilterObj) {
      return undefined;
    }
    switch (dimensionName) {
      case DistroFilterDimensionEnum.API_VERSION:
        return distroFilterObj.apiVersion;
      case DistroFilterDimensionEnum.SCREEN_SHAPE:
        return distroFilterObj.screenShape;
      case DistroFilterDimensionEnum.SCREEN_WINDOW:
        return distroFilterObj.screenWindow;
      default:
        return undefined;
    }
  }

  /**
   * 获取FA模型中distroFilterObj
   * @param projectModel
   * @param entryName
   * @private
   */
  public static getFADistroFilterConfig(projectModel: ProjectModel, entryName: string): DistroFilterConfig | undefined {
    // 若target中定制distroFilter则优先读取:entryModuleModel->build-profile.json5->targetOpt{}->config->distroFilter{}
    const curModuleExecutableTargets = this.getCurModuleExecutableTargets(projectModel, entryName);
    if (curModuleExecutableTargets[0].target?.config?.distroFilter) {
      // 此处list仅存在一个target,若存在多个可执行target则不会走到此处逻辑,故直接取0
      return {
        moduleName: entryName,
        distroFilterObj: curModuleExecutableTargets[0].target?.config?.distroFilter,
      };
    }

    // 若无target定制则解析读取config.json文件:entryModuleModel->config.json->module->distroFilter{}
    const configJsonObj = this.getConfigOptObj(projectModel, entryName);
    const distroFilterObj = configJsonObj.module.distroFilter;
    return distroFilterObj === undefined ? undefined : { moduleName: entryName, distroFilterObj: distroFilterObj };
  }

  /**
   * 获取指定模块apply至当前product下的target集合
   * @param projectModel
   * @param moduleName
   * @private
   */
  public static getCurModuleExecutableTargets(projectModel: ProjectModel, moduleName: string): ModuleTargetOpt[] {
    const curProduct = findTargetProduct(projectModel);
    const buildProfileOpt = projectModel.getProfileOpt();
    const moduleTargetOptList: ModuleTargetOpt[] = [];

    // 遍历工程级build-profile.json5中的modules配置数组,获取当前指定模块的product-target配置
    buildProfileOpt.modules.forEach((moduleOpt) => {
      if (moduleOpt.name === moduleName) {
        const moduleModel = projectModel.getModuleModelByName(moduleName);
        const moduleTargetOptions = moduleModel?.getTargetOptions();

        // 遍历modules->targets中的的每一个target配置数组,获取当前模块target applyTo的所有product集合
        // 此target配置为工程级别配置:{name,applyToProducts[]}
        moduleOpt.targets?.forEach((projectTargetBuildOpt) => {
          // 通过工程级target配置寻找模块级target配置:{name,config{},runtimeOS...}
          const moduleTargetBuildOpt = moduleTargetOptions?.find((moduleTargetBuildOpt) => {
            return moduleTargetBuildOpt.name === projectTargetBuildOpt.name;
          });

          // 遍历模块target的applyToProducts,以获取当前指定的product下的moduleTargetOpt集合
          projectTargetBuildOpt.applyToProducts.forEach((productName) => {
            if (productName === curProduct.name) {
              const moduleTargetOpt = {
                moduleName: moduleOpt.name,
                target: moduleTargetBuildOpt,
              };
              moduleTargetOptList.push(moduleTargetOpt);
            }
          });
        });
      }
    });
    return moduleTargetOptList;
  }

  /**
   * 获取指定模块当前可执行target的name集合 用于报错日志提示信息
   * @param projectModel
   * @param entryName
   */
  private static getCurModuleExecutableTargetNameList(projectModel: ProjectModel, entryName: string): string[] {
    const curModuleExecutableTargets = DistroFilterHandler.getCurModuleExecutableTargets(projectModel, entryName);
    const curModuleExecutableTargetNameList: string[] = [];
    curModuleExecutableTargets.forEach((curModuleExecutableTarget) => {
      if (curModuleExecutableTarget.target) {
        curModuleExecutableTargetNameList.push(curModuleExecutableTarget.target.name);
      }
    });
    return curModuleExecutableTargetNameList;
  }

  /**
   * 获取工程中当前product下可执行target的distroFilter集合
   * @param projectModel
   */
  public static getCurExecutableTargetsDistroFilterConfigList(projectModel: ProjectModel): DistroFilterConfig[] {
    const distroFilterConfigList: DistroFilterConfig[] = [];
    projectModel.getAllEntryModules().forEach((entryName) => {
      const curModuleExecutableTargets = this.getCurModuleExecutableTargets(projectModel, entryName);
      if (curModuleExecutableTargets.length > 1) {
        curModuleExecutableTargets.forEach((curModuleExecutableTarget) => {
          const curModuleExecutableTargetDistroFilterConfig = this.getTargetDistroFilterConfig(projectModel, entryName, curModuleExecutableTarget);
          distroFilterConfigList.push(curModuleExecutableTargetDistroFilterConfig);
        });
      }
    });
    return distroFilterConfigList;
  }

  /**
   * 获取通用维度distroFilter配置对象的value
   * 通用维度:policy可以配置include/exclude && value存在已定义类型的取值范围
   * 例:apiVersion,screenShape,screenDensity,countryCode;screenWindow仅支持include
   * @param distroFilterConfig distroFilter配置
   * @param valueScope value取值范围
   * @param dimensionName 指定校验维度
   * @param errorLog 错误退出日志
   * @protected
   */
  protected getCommonDimensionValue(
    distroFilterConfig: DistroFilterConfig,
    valueScope: (string | number)[],
    dimensionName: string,
    errorLog: () => void,
  ): number[] | string[] | undefined {
    const entryName = distroFilterConfig.moduleName;
    const moduleModel = this.projectModel.getModuleModelByName(entryName) as CoreModuleModelImpl;
    const detailFilePath = DistroFilterHandler.getDetailFilePath(this.projectModel, moduleModel);
    const curModuleExecutableTargetNameList = DistroFilterHandler.getCurModuleExecutableTargetNameList(this.projectModel, entryName);
    if (!distroFilterConfig.distroFilterObj) {
      this.logger
        ._buildError('DistroFilter must be configured for all executable targets of the entry module.')
        ._detail('The distroFilter is missing for the executable targets' + ` [${curModuleExecutableTargetNameList}] of the ${entryName}.`)
        ._file(detailFilePath)
        ._printErrorAndExit();
    }
    const distroFilterObj = this.getDistroFilterObjByDimension(distroFilterConfig.distroFilterObj, dimensionName);
    if (!distroFilterObj) {
      return undefined;
    }

    const distroObjPolicy = distroFilterObj.policy;
    const distroObjValue = distroFilterObj.value;
    if (!distroObjValue) {
      this.logger
        ._buildError(`The ${dimensionName} value configuration is incorrect.`)
        ._detail(`Please check whether the distroFilter configuration in module '${entryName}' is correct.`)
        ._file(detailFilePath)
        ._printErrorAndExit();
    }
    distroObjValue.forEach((value) => {
      if (!valueScope.includes(value)) {
        errorLog();
      }
    });
    if (distroObjPolicy === 'include' && isSubset(valueScope, distroObjValue)) {
      return distroObjValue;
    } else if (distroObjPolicy === 'exclude') {
      return complementarySet(valueScope, distroObjValue);
    } else {
      return undefined;
    }
  }

  /**
   * 获取distroFilter校验报错时跳转文件链接
   * @param projectModel
   * @param moduleModel
   */
  public static getDetailFilePath(projectModel: ProjectModel, moduleModel: CoreModuleModelImpl | undefined): string {
    if (!moduleModel) {
      return '';
    }
    const projectDir = projectModel.getProjectDir();
    const moduleNodeDir = moduleModel.getModule().getNodeDir();
    const curModuleExecutableTargets = this.getCurModuleExecutableTargets(projectModel, moduleNodeDir);
    const existInTarget = curModuleExecutableTargets.length === 1 && curModuleExecutableTargets[0].target?.config?.distroFilter;
    return path.resolve(
      projectDir,
      moduleNodeDir,
      this.validateMultiTarget(projectModel) || existInTarget ? `${CommonConst.PROFILE_JSON5}` : `src/main/${CommonConst.CONFIG_JSON}`,
    );
  }

  /**
   * 获取target定制设备类型
   * @param projectModel
   * @param entryName
   * @param moduleTargetOpt
   */
  public static getTargetDeviceType(projectModel: ProjectModel, entryName: string, moduleTargetOpt: ModuleTargetOpt): string[] {
    return moduleTargetOpt.target?.config?.deviceType
      ? moduleTargetOpt.target?.config.deviceType
      : this.getConfigOptObj(projectModel, entryName).module.deviceType;
  }

  /**
   * 获取target定制distroFilterConfig
   * @param projectModel
   * @param entryName
   * @param executableTarget
   */
  public static getTargetDistroFilterConfig(projectModel: ProjectModel, entryName: string, executableTarget: ModuleTargetOpt): DistroFilterConfig {
    const configOptObj: ConfigOptObj = this.getConfigOptObj(projectModel, entryName);
    return executableTarget.target?.config?.distroFilter
      ? {
          moduleName: entryName,
          distroFilterObj: executableTarget.target.config.distroFilter,
        }
      : {
          moduleName: entryName,
          distroFilterObj: configOptObj.module.distroFilter,
        };
  }

  /**
   * 通过config.json获取config配置Obj
   * @param projectModel
   * @param entryName
   */
  public static getConfigOptObj(projectModel: ProjectModel, entryName: string): ConfigOptObj {
    const configJsonPath = path.resolve(projectModel.getProjectDir(), entryName, `src/main/${CommonConst.CONFIG_JSON}`);
    return resModelLoader.getConfigJson(configJsonPath);
  }

  /**
   * 获取当前工程所有entry模块的设备类型集合
   * @param projectModel projectModel
   * @private
   */
  private static getDeviceTypeList(projectModel: ProjectModel): string[][] {
    const allEntryModules = projectModel.getAllEntryModules();
    const deviceTypeList: string[][] = [];
    allEntryModules.forEach((entryName) => {
      const moduleModel = projectModel.getModuleModelByName(entryName);
      if (moduleModel === undefined) {
        return;
      }
      const deviceTypes = moduleModel.getDeviceTypes();
      deviceTypeList.push(deviceTypes);
    });
    return deviceTypeList;
  }

  /**
   * 检查指定校验维度distroFilter配置是否为空,若为空返回true
   * @param distroFilterConfig
   * @param dimensionName 指定校验维度
   */
  public checkDimensionConfigEmpty(distroFilterConfig: DistroFilterConfig, dimensionName: string): boolean {
    return this.getDistroFilterObjByDimension(distroFilterConfig.distroFilterObj, dimensionName) === undefined;
  }

  /**
   * 校验工程entry模块distroFilter标签是否存在且正确配置
   * @private
   */
  private checkDistroFilterLabel(): void {
    let cause = '';
    let detail = '';
    const curProduct = findTargetProduct(this.projectModel);
    this.projectModel.getAllEntryModules().forEach((entryModule) => {
      const moduleModel = this.projectModel.getModuleModelByName(entryModule) as CoreModuleModelImpl;
      const curModuleExecutableTargetNameList = DistroFilterHandler.getCurModuleExecutableTargetNameList(this.projectModel, entryModule);
      const detailFilePath = DistroFilterHandler.getDetailFilePath(this.projectModel, moduleModel);
      if (DistroFilterHandler.validateMultiTarget(this.projectModel)) {
        if (!DistroFilterHandler.checkExistTargetDistroFilter(this.projectModel)) {
          cause =
            'When multiple targets in the current entry module are applied to the current product, ' +
            `the executable targets in ${CommonConst.PROFILE_JSON5} file must contain the distroFilter label, ` +
            'and the settings of this label must be able to uniquely identify an target.';
          detail =
            'Add the distroFilter label under target-config tag in all executable targets ' +
            `[${curModuleExecutableTargetNameList}] which applied to '${curProduct.name}' product ` +
            `in the '${entryModule}' ${CommonConst.PROFILE_JSON5} file.`;
          this.logger._buildError(cause)._detail(detail)._file(detailFilePath)._printErrorAndExit();
        }
      } else if (DistroFilterHandler.validateMultiEntry(this.projectModel)) {
        const intersectedEntryList = DistroFilterHandler.findIntersectedEntryList(this.projectModel, entryModule);
        if (intersectedEntryList.length !== 0) {
          cause =
            'When multiple entry modules exist the same device type, ' +
            `the ${CommonConst.CONFIG_JSON} or ${CommonConst.PROFILE_JSON5} file must contain the distroFilter label, ` +
            'and the settings of this label must be able to uniquely identify an entry module.';
          detail =
            'Check the distroFilter label under module tag in the ' +
            `'${entryModule}' and '${intersectedEntryList}' ${CommonConst.CONFIG_JSON} file or ` +
            `their target config in ${CommonConst.PROFILE_JSON5} file.`;
          const distroFilterConfig = DistroFilterHandler.getFADistroFilterConfig(this.projectModel, entryModule);
          if (!distroFilterConfig) {
            this.logger._buildError(cause)._detail(detail)._file(detailFilePath)._printErrorAndExit();
          }
        }
      }
    });
  }

  /**
   * 检查当前工程任一可执行target是否存在定制distroFilter标签
   * @param projectModel
   */
  private static checkExistTargetDistroFilter(projectModel: ProjectModel): boolean {
    const curExecutableTargetsDistroFilterConfigList = this.getCurExecutableTargetsDistroFilterConfigList(projectModel);
    return curExecutableTargetsDistroFilterConfigList.some((curExecutableTargetsDistroFilterConfig) => {
      return curExecutableTargetsDistroFilterConfig.distroFilterObj !== undefined;
    });
  }

  /**
   * 检查是否启用对target定制场景的distroFilter校验
   * 当前工程中若任一entry模块存在多个apply至同一product下的target,则需要对target启用distroFilter校验
   * @param projectModel
   */
  public static validateMultiTarget(projectModel: ProjectModel): boolean {
    for (const entryName of projectModel.getAllEntryModules()) {
      const curModuleExecutableTargets = DistroFilterHandler.getCurModuleExecutableTargets(projectModel, entryName);
      if (curModuleExecutableTargets.length > 1) {
        return true;
      }
    }
    return false;
  }

  /**
   * 查找与指定entry模块存在设备类型交集的entry模块集合
   * @param projectModel
   * @param sourceEntry
   */
  public static findIntersectedEntryList(projectModel: ProjectModel, sourceEntry: string): string[] {
    const sourceEntryModuleModel = projectModel.getModuleModelByName(sourceEntry);
    const intersectedEntryList: string[] = [];
    if (!sourceEntryModuleModel) {
      return [];
    }
    const sourceDeviceTypes = sourceEntryModuleModel.getDeviceTypes();
    const allEntryModules = projectModel.getAllEntryModules();
    allEntryModules.delete(sourceEntry);
    for (const targetEntry of allEntryModules) {
      const targetEntryModuleModel = projectModel.getModuleModelByName(targetEntry);
      if (!targetEntryModuleModel) {
        continue;
      }
      const targetDeviceTypes = targetEntryModuleModel.getDeviceTypes();
      if (checkIntersection(sourceDeviceTypes, targetDeviceTypes)) {
        intersectedEntryList.push(targetEntry);
      }
    }
    return intersectedEntryList;
  }

  /**
   * 检查指定模块下多个可执行target的设备类型是否存在交集以确定是否对多target进行distroFilter校验
   * @param projectModel
   * @param moduleName
   * @param entryExecutableTargetList
   * @private
   */
  public static checkSingleEntryTargetDeviceType(projectModel: ProjectModel, moduleName: string, entryExecutableTargetList: ModuleTargetOpt[]): boolean {
    const checkDeviceSet: Set<string> = new Set<string>();
    for (const executableTargetOpt of entryExecutableTargetList) {
      const deviceTypes = DistroFilterHandler.getTargetDeviceType(projectModel, moduleName, executableTargetOpt);
      for (const deviceType of deviceTypes) {
        if (checkDeviceSet.has(deviceType)) {
          return true;
        }
        checkDeviceSet.add(deviceType);
      }
    }
    return false;
  }

  /**
   * 检查是否启用对多entry场景的distroFilter校验
   * @param projectModel
   */
  public static validateMultiEntry(projectModel: ProjectModel): boolean {
    const checkDeviceSet: Set<string> = new Set<string>();
    for (const deviceTypes of this.getDeviceTypeList(projectModel)) {
      for (const deviceType of deviceTypes) {
        if (checkDeviceSet.has(deviceType)) {
          return true;
        }
        checkDeviceSet.add(deviceType);
      }
    }
    return false;
  }

  /**
   * 查找stage模型module.json5的metadata数组定义资源对象中第一个包含distroFilter配置的资源对象
   * @param projectDir
   * @param moduleModel
   * @param metadataList
   * @private
   */
  public static findFirstDistroFilterConfigMetadata(
    projectDir: string,
    moduleModel: CoreModuleModelImpl,
    metadataList: MetadataObj[] | undefined,
  ): MetadataObj | undefined {
    if (!metadataList) {
      return undefined;
    }
    const moduleNodeDir = moduleModel.getModule().getNodeDir();
    return metadataList.find((metadataObj) => {
      if (metadataObj.resource) {
        const profileName = parsingProfileName(metadataObj.resource);
        const profilePath = path.resolve(projectDir, moduleNodeDir, `src/main/${BuildDirConst.RESOURCES_BASE_PROFILE_DIR}/${profileName}.json`);
        const profileObj = getJson5Obj(profilePath);
        return profileObj['distroFilter'] || profileObj['distributionFilter'];
      } else {
        return undefined;
      }
    });
  }

  /**
   * 检查module.json5中metadata数组定义资源对象是否包含distroFilter配置
   * @param projectDir
   * @param moduleModel
   * @param metadataList
   * @private
   */
  public static checkMetadataExistDistroFilterConfig(projectDir: string, moduleModel: CoreModuleModelImpl, metadataList: MetadataObj[] | undefined): boolean {
    if (!metadataList) {
      return false;
    }
    return this.findFirstDistroFilterConfigMetadata(projectDir, moduleModel, metadataList) !== undefined;
  }
}

/**
 * 模块-distroFilter配置对象
 */
export interface DistroFilterConfig {
  moduleName: string;
  distroFilterObj: DistroFilterBuildOpt | undefined;
}

/**
 * 模块-target配置对象
 */
export interface ModuleTargetOpt {
  moduleName: string;
  target: ModuleTargetBuildOpt | undefined;
}
